Android 开发中,加载图片的一些代码笔记。
计算源图片宽高
图片源文件和目标 View 之间,大部分情况下,不会完全地等宽等高,所以需要对图片进行压缩。
压缩图片需要用到 BitmapFactory.Options
,具体用法如下。
1 | BitmapFactory.Options options = new BitmapFactory.Options(); |
其中
1 | options.inJustDecodeBounds = true; |
设置为 inJustDecodeBounds 为 true 表示不把整个图片加载进内存中,只是测量其宽高,MIME TYPE 等信息。
计算压缩比例
如果目标的 View 比源图片小,就需要对图片进行压缩,可以通过以下代码片段计算出缩放比例。
1 | if (sourceHeight > targetHeight || sourceWidth > targetWidth) { |
计算出 inSampleSize 之后,不再需要测量图片,而是要加载图片,将 inJustDecodeBounds 设置为 false
1 | options.inJustDecodeBounds = false; |
编码图片,这里的 inSampleSize 只会取最近的一个 2 的整数次幂(向下取整),比如计算出来的 inSampleSize 是 7,那么实际上是 4.
也就是宽和高同时除以 2,整个面积变为原来的 1/4.
1 | FileInputStream fileInputStream = new FileInputStream(file); |
这样子编码出来的 bitmap 对象,所占的内存就是参照 目标 View 计算出来的,相对合理。
再次压缩图片
由于 inSampleSize 参数的限制,所以,压缩后的图片不一定是效果最好的(一般情况下都不是),这个时候, bitmap 所占的内存已经比较小了,可以使用 createScaleBitmap 方法再次进行缩放,这个操作是 bitmap 上进行操作的,所以压缩返回新对象之后,需要将原来的 bitmap 对象回收。
1 | private static Bitmap createScaleBitmap(Bitmap src, int targetWidth, int targetHeight) { |
获取 View 的宽高
获取 View 的宽高时候,可能会出现取值为 0 的情况,出现这种情况,可能的原因是:整个 ViewTree 并没有绘制完成。
参考一个 stackoverflow 上的回答,对 ViewTree 进行监听,当绘制完成之后,再获取 View 的宽高。
1 | final TextView tv = (TextView)findViewById(R.id.venueLabel); |